/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frcmd_server.c                                     */
/*  NOTE      =                                                    */
/*  DATE      = 2014/11/17 by guojq                                */
/*******************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>

#include "frcomm.h"
#include "frmem.h"
#include "frlog.h"
#include "frame.h"
#include "frconfig.h"
#include "client.pb-c.h"
#include "frfilter.h"
#include "frcmd_server_l7.h"
#include "frproto_l7default.h"
#include "frmodule_mng.h"
#include "conntrack.h"
#include "frame_params.h"
#include "frct_comm.h"
#include "frct_mng.h"
#include "frct_hash.h"
#include "frstat_module.h"
#include "frstat_ct.h"
#include "frstat_system.h"
#include "frstat_thread.h"
#include "frstat_topology.h"
#include "frstat_server.h"

/* 最大监听个数 */
#define FRCMD_MAX_LISTEN     10
#define FRCMD_MAX_ONELINE    1024
/* 忙碌 */
#define FRCMD_SERVER_BUSY      "The server is in busy now, please wait for a moment\n"
/* 不支持 */
#define FRCMD_SERVER_NOT_SUPPORT     "The command is not support\n"
/* 结果集空 */
#define FRCMD_SERVER_OK        "The result is OK\n"

#define FRCMD_SERVER_END        "broada"

#define COMMIT_CMD             "commit"
#define ROLLBACK_CMD           "rollback"

#define FILTER_CMD             "filter"

#define FILTER_CMD_ADD         "add"
#define FILTER_CMD_DEL         "del"
#define FILTER_CMD_CLEAR       "clear"

#define PRINT_CMD_SYSTEM       "system"
#define PRINT_CMD_CT           "ct"
#define PRINT_CMD_TOPOLOGY     "topology"
#define PRINT_CMD_THREAD       "thread"
#define PRINT_CMD_MODULE       "module"
#define PRINT_CMD_SERVER       "server"
#define PRINT_CMD_FILTER       "filter"
#define PRINT_CMD_L7           "l7"
#define PRINT_CMD_JAVA         "java"
#define PRINT_CMD_MEMORY       "memory"

FR_STATIC int g_i_busy = 0;
FR_STATIC pthread_rwlock_t g_cmd_rwlock;

union int_arr4 {
    uint32_t ui_len;
    char arr_data[4];
};

/*******************************************************************************
*  FUNC     :  执行print的命令
*              print system/ct/topology/thread/module/server/filter/l7_default/java/memory [L7_protocol]
*  ARGS     :  p_command(命令行)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __do_print(Command *p_command, char **pp_result, int accept_sock)
{
    char *p_cmd = p_command->print_cmd->cmd;
    char *p_out = NULL;
    int i_ret = FR_FAIL;
    char *p_ret_tmp1 = NULL;
    char *p_ret_tmp2 = NULL;

    if (p_cmd == NULL)
        return FR_FAIL;
    
    //system
    if (strncasecmp(p_cmd, PRINT_CMD_SYSTEM, strlen(PRINT_CMD_SYSTEM)) == 0)
    {
        frstat_system_output(pp_result);
        if(pp_result)
            i_ret = FR_SUCC;
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_CT, strlen(PRINT_CMD_CT)) == 0)
    {
        frdbg("run frct_stat_all...\n");
        //frct_hash_output(pp_result);
        if(p_command->print_cmd->n_args == 0)
            frstat_ct_all(pp_result, accept_sock);
        else
        {
            if (strcasecmp(p_command->print_cmd->args[0], "all") == 0)
                frstat_ct_l7(pp_result, -1, accept_sock);
            else if (strcasecmp(p_command->print_cmd->args[0], "unknown") == 0)
                frstat_ct_l7(pp_result, -2, accept_sock);
            else
                frstat_ct_l7(pp_result, atoi(p_command->print_cmd->args[0]), accept_sock);
        }
        if(pp_result)
            i_ret = FR_SUCC;
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_TOPOLOGY, strlen(PRINT_CMD_TOPOLOGY)) == 0)
    {
        //if (frstat_topology_report(accept_sock) != FR_SUCC)
        {
            p_out = frmalloc(128);

            snprintf(p_out, 128, "print topology failed\n");
            *pp_result = p_out;
        }
        i_ret = FR_SUCC;
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_THREAD, strlen(PRINT_CMD_THREAD)) == 0)
    {
        frstat_thread_output(pp_result);
        i_ret = FR_SUCC;
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_MODULE, strlen(PRINT_CMD_MODULE)) == 0)
    {
        if(p_command->print_cmd->n_args > 0)
        {
            if(strcasecmp(p_command->print_cmd->args[0],"config")==0)
            {
                frmodule_mng_output(&p_ret_tmp1);
                frproto_l7default_output(&p_ret_tmp2);
                if(p_ret_tmp1 != NULL && p_ret_tmp2 != NULL)
                {
                    //p_ret_tmp1 p_ret_tmp2  '\n'  '\0'
                    p_out = frmalloc(strlen(p_ret_tmp1) + strlen(p_ret_tmp2) + 2);
                    if(!p_out)
                    {
                        frfree(p_ret_tmp1);
                        frfree(p_ret_tmp2);
                        return FR_FAIL;
                    }

                    snprintf(p_out,strlen(p_ret_tmp1) + strlen(p_ret_tmp2) + 2,"%s\n%s",p_ret_tmp1,p_ret_tmp2);
                    frfree(p_ret_tmp1);
                    frfree(p_ret_tmp2);
                    *pp_result = p_out;
                    i_ret = FR_SUCC;
                }
                else if(p_ret_tmp1 != NULL)
                {
                    *pp_result = p_ret_tmp1;
                    i_ret = FR_SUCC;
                }
                else if(p_ret_tmp2 != NULL)
                {
                    *pp_result = p_ret_tmp2;
                    i_ret = FR_SUCC;
                }
                else
                    i_ret = FR_FAIL;
            }
            else if(strcasecmp(p_command->print_cmd->args[0],"stat")==0)
            {
                frstat_module_output(pp_result);
                if(pp_result)
                    i_ret = FR_SUCC;
            }
        }
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_SERVER, strlen(PRINT_CMD_SERVER)) == 0)
    {
        frstat_server_output(pp_result);
        i_ret = FR_SUCC;
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_FILTER, strlen(PRINT_CMD_FILTER)) == 0)
    {
        i_ret = apm_filter_show(pp_result);
        if(*pp_result)
            p_out = *pp_result;
        frdbg("apm_filter_show \n[%s], [%d]\n", p_out, i_ret);
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_L7, strlen(PRINT_CMD_L7)) == 0)
    {
        char *p_value = NULL, *p_l7_default = NULL;

        i_ret = frconfig_get_string(APM_CFG_FILENAME_ANALYZER, APM_ANALYZER_KEY_PROTOCOLS_LOAD, &p_value);
        if (i_ret == APM_FRCONFIG_SUCC)
        {
            i_ret = frconfig_get_string(APM_CFG_FILENAME_ANALYZER, APM_ANALYZER_KEY_L7_DEFAULT, &p_l7_default);
            if (i_ret == APM_FRCONFIG_SUCC)
            {
                char *p_out = NULL;
                int i_outlen = (p_value ? strlen(p_value) : 0) + (p_l7_default ? strlen(p_l7_default) : 0) + 1;

                p_out = frmalloc(i_outlen + 128);
                if (p_out)
                {
                    snprintf(p_out, i_outlen + 128, "Tcp_Proto=%s\nL7_Proto=%s\n", p_value, p_l7_default);
                    *pp_result = p_out;
                }
            }
        }
        if (p_value)
            frfree(p_value);
        if (p_l7_default)
            frfree(p_l7_default);
        i_ret = FR_SUCC;
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_JAVA, strlen(PRINT_CMD_JAVA)) == 0)
    {
        if(st_apm_params.arr_zmq_connect[0] != '\0')
        {
            p_out = frmalloc(strlen(st_apm_params.arr_zmq_connect) + 1);
            if(!p_out)
                return FR_FAIL;

            snprintf(p_out,strlen(st_apm_params.arr_zmq_connect) + 1,"%s",st_apm_params.arr_zmq_connect);
            pp_result = &p_out;
            i_ret = FR_SUCC;
        }
    }
    else if (strncasecmp(p_cmd, PRINT_CMD_MEMORY, strlen(PRINT_CMD_MEMORY)) == 0)
    {
        fr_slab_stat(pp_result);
        if(pp_result)
            i_ret = FR_SUCC;
    }
    else
        return FR_FAIL;
    
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  执行commit的命令
*  ARGS     :  p_command(命令行)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __do_commit(Command *p_command)
{
    int i_action = p_command->commit_cmd->action;
    int i_cmd = p_command->commit_cmd->cmd;

    if (i_cmd == COMMIT_COMMAND__TYPE__FILTER)
    {
        if (i_action == COMMIT_COMMAND__ACTION__Commit)
        {
            frdbg("apm_filter_commit start\n");
            apm_filter_commit();
            return FR_SUCC;
        }
        else if (i_action == COMMIT_COMMAND__ACTION__Rollback)
        {
            frdbg("apm_filter_rollback start\n");
            apm_filter_rollback();
            return FR_SUCC;
        }
        return FR_FAIL;
    }
    if (i_cmd == COMMIT_COMMAND__TYPE__L7)
    {
        if (i_action == COMMIT_COMMAND__ACTION__Commit)
        {
            frdbg("apm_filter_commit start\n");
            do_l7_commit();
            return FR_SUCC;
        }
        else if (i_action == COMMIT_COMMAND__ACTION__Rollback)
        {
            frdbg("apm_filter_rollback start\n");
            do_l7_rollback();
            return FR_SUCC;
        }
        return FR_FAIL;
    }
    if (i_cmd == COMMIT_COMMAND__TYPE__L7_DEFAULT)
    {
        if (i_action == COMMIT_COMMAND__ACTION__Commit)
        {
            frdbg("do_l7_default_commit start\n");
            do_l7_default_commit();
            return FR_SUCC;
        }
        else if (i_action == COMMIT_COMMAND__ACTION__Rollback)
        {
            frdbg("do_l7_default_rollback start\n");
            do_l7_default_rollback();
            return FR_SUCC;
        }
        return FR_FAIL;
    }
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  执行filter的命令
*  ARGS     :  p_command(命令行)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __do_filter(Command *p_command)
{
    Filter *p_filter = NULL;
    char *p_action = p_command->filter_cmd->action;

    if (p_action == NULL)
        return FR_FAIL;

    if (strncasecmp(p_action, FILTER_CMD_CLEAR, strlen(FILTER_CMD_CLEAR)) == 0)
    {
        frdbg("apm_filter_clear start\n");
        apm_filter_clear();
        return FR_SUCC;
    }

    p_filter = p_command->filter_cmd->filters[0];
    if (p_filter == NULL || p_filter->ip_from == NULL || p_filter->ip_to == NULL
     || p_filter->port_from == NULL || p_filter->port_to == NULL || p_filter->mac == NULL)
        return FR_FAIL;

    if (strncasecmp(p_action, FILTER_CMD_ADD, strlen(FILTER_CMD_ADD)) == 0)
    {
        frdbg("apm_prepare_add start, mac=[%s], proto=[%d], ip_from=[%s], ip_to=[%s], port_from=[%s], port_to=[%s]\n"
            , p_filter->mac, p_filter->ip_proto, p_filter->ip_from, p_filter->ip_to, p_filter->port_from, p_filter->port_to);
        apm_prepare_add(1, p_filter->mac, p_filter->ip_proto, p_filter->ip_from, p_filter->ip_to, p_filter->port_from, p_filter->port_to);
    }
    else if (strncasecmp(p_action, FILTER_CMD_DEL, strlen(FILTER_CMD_DEL)) == 0)
    {
        frdbg("apm_prepare_del start, mac=[%s], proto=[%d], ip_from=[%s], ip_to=[%s], port_from=[%s], port_to=[%s]\n"
            , p_filter->mac, p_filter->ip_proto, p_filter->ip_from, p_filter->ip_to, p_filter->port_from, p_filter->port_to);
        apm_prepare_del(p_filter->mac, p_filter->ip_proto, p_filter->ip_from, p_filter->ip_to, p_filter->port_from, p_filter->port_to);
    }
    else
        return FR_FAIL;
    
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  退出程序处理
*  ARGS     :  
*  RTN      :  
*  NOTE     :
*******************************************************************************/
void __do_exit(void)
{
    //todo
    //退出处理
    g_i_flag_run = 0;
}

/*******************************************************************************
*  FUNC     :  根据收到的命令做相应操作
*  ARGS     :  p_command(命令行)
*           :  pp_result(结果集)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __do_command(char *p_cmd
                         , int i_cmd_len
                         , char **pp_result
                         , int accept_sock)
{
    int i_ret = 0;
    Command *p_command = NULL;
    
    p_command = command__unpack(NULL, i_cmd_len, (const uint8_t *)p_cmd);
    if (p_command == NULL)
    {
        FRLOG_DEBUG_DETAIL("unpack failed!\n");
        return FR_FAIL;
    }

    switch (p_command->cmd_type)
    {
        case COMMAND__COMMAND_TYPE__Type_ModuleCommand:
            i_ret = do_module_cmd(p_command);
            break;
        case COMMAND__COMMAND_TYPE__Type_L7Command:
            i_ret = do_l7_cmd(p_command);
            break;
        case COMMAND__COMMAND_TYPE__Type_L7Default:
            i_ret = do_l7default_cmd(p_command);
            break;
        case COMMAND__COMMAND_TYPE__Type_FilterCommand:
            i_ret = __do_filter(p_command);
            break;
        case COMMAND__COMMAND_TYPE__Type_JavaCommand:
            break;
        case COMMAND__COMMAND_TYPE__Type_CommitCommand:
            i_ret = __do_commit(p_command);
            break;
        case COMMAND__COMMAND_TYPE__Type_PrintCommand:
            i_ret = __do_print(p_command, pp_result, accept_sock);
            break;
        case COMMAND__COMMAND_TYPE__Type_ExportCommand:
            break;
        case COMMAND__COMMAND_TYPE__Type_ExitCommand:
            __do_exit();
            break;
        default:
            break;
    }
    command__free_unpacked(p_command, NULL);
    //todo
//    printf("cmd=[%s]\n", p_command);
//    *pp_result = frstrdup("command ok");
//    printf("exist start\n");
//    frame_cmd_exist();
//    printf("exist start\n");

    return i_ret;
}

/*******************************************************************************
*  FUNC     :  创建监听
*  ARGS     :  us_port(监听端口)
*           :  p_listen_sock(socket句柄)
*  RTN      :  0 (success)
*           :  1 (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __create_listen(unsigned short us_port, int *p_listen_sock)
{
    int i_ret = 0;
    int listen_sock = 0;
    int i_reuse=1;
    struct sockaddr_in host_addr;
    memset((void *)&host_addr, 0, sizeof(host_addr));

    host_addr.sin_family = AF_INET;
    host_addr.sin_port = htons(us_port);
    host_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    /* 创建监听socket */
    listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_sock < 0)
    {
        FRLOG_ERROR_DETAIL("create socket failed\n");
        return 1;
    }
    if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &i_reuse, sizeof(i_reuse)) == -1)
    {
        FRLOG_ERROR_DETAIL("setsockopt failed");
        close(listen_sock);
        return 1;
    }

    /* 绑定端口 */
    i_ret = bind(listen_sock, (struct sockaddr *)&host_addr, sizeof(host_addr));
    if(i_ret < 0)
    {
        FRLOG_ERROR_DETAIL("bind[%d] socket failed\n", us_port);
        close(listen_sock);
        return 1;
    }

    /* 监听 */
    i_ret = listen(listen_sock, FRCMD_MAX_LISTEN);
    if(i_ret < 0)
    {
        FRLOG_ERROR_DETAIL("listen[%d] socket failed\n", us_port);
        close(listen_sock);
        return 1;
    }

    *p_listen_sock = listen_sock;
    return 0;
}

/*******************************************************************************
*  FUNC     :  发送数据包
*  ARGS     :  sockfd(socket句柄)
*           :  p_data(要发送的数据)
*           :  ui_data_len(数据长度)
*  RTN      :  0 (success)
*           :  1 (failed)
*  NOTE     :
*******************************************************************************/
int frcmd_send_data(int sockfd
                  , char *p_data
                  , unsigned int ui_data_len)
{
    int i_first_flg = 1;
    int i_ret_len = 0;
    unsigned int ui_send_len = 0;
    union int_arr4 u_int_arr4;
    uint32_t u32_data_len = 0;
    char *p_data_tmp = 0;
    char arr_len_data[FRCMD_MAX_ONELINE + 1] = {0x0};

    //frdbg("send data=[%s]\n", p_data);

    while (ui_data_len)
    {
        /* 第一次要将文件长度加在头结点发送出去 */
        if (i_first_flg == 1)
        {
            i_first_flg = 0;
            /* 将本地字节序转换成网络字节序 */
            u32_data_len = htonl(ui_data_len);
            u_int_arr4.ui_len = ui_data_len;
            memcpy(arr_len_data, u_int_arr4.arr_data, 4);
            p_data_tmp = arr_len_data;
            p_data_tmp += 4;
            ui_send_len = ui_data_len > (FRCMD_MAX_ONELINE - 4)?(FRCMD_MAX_ONELINE - 4):ui_data_len;
            memcpy(p_data_tmp, p_data, ui_send_len);
            i_ret_len = send(sockfd, arr_len_data, ui_send_len + 4, 0);
            if(i_ret_len <= 0)
            {
                return 1;
            }
        }
        else
        {
            ui_send_len = ui_data_len > FRCMD_MAX_ONELINE?FRCMD_MAX_ONELINE:ui_data_len;
            i_ret_len = send(sockfd, p_data, ui_send_len, 0);
            if(i_ret_len <= 0)
            {
                return 1;
            }
        }
        p_data += ui_send_len;
        ui_data_len -= ui_send_len;
    }

    return 0;
}

/*******************************************************************************
*  FUNC     :  线程处理函数
*  ARGS     :  args(socket句柄)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void *__srv_recv_func(void *args)
{
    int i_ret = 0;
    int i_rcv_len = 0;
    int i_status = 0;
    int accept_sock = *(int *)args;
    char *p_result = NULL;
    char arr_rcv_cmd[FRCMD_MAX_ONELINE + 1];

    //与主线程分离
    pthread_detach(pthread_self());

    memset(arr_rcv_cmd, 0x00, sizeof(arr_rcv_cmd));
    i_rcv_len = recv(accept_sock, arr_rcv_cmd, sizeof(arr_rcv_cmd) - 1, 0);
    if(i_rcv_len < 0)
    {
        FRLOG_ERROR_DETAIL("recv socket failed\n");
        close(accept_sock);
        pthread_exit(0);
        return (void*)NULL;
    }
    frdbg("receive cmd:[%s]\n", arr_rcv_cmd);

    /*根据接收到的名命令,发送响应的数据 */
    pthread_rwlock_rdlock(&g_cmd_rwlock);
    i_status = g_i_busy;
    pthread_rwlock_unlock(&g_cmd_rwlock);
    /* 其他线程正在处理 */
    if (i_status == 1)
    {
        i_ret = frcmd_send_data(accept_sock, FRCMD_SERVER_BUSY, strlen(FRCMD_SERVER_BUSY));
        i_ret += frcmd_send_data(accept_sock, FRCMD_SERVER_END, strlen(FRCMD_SERVER_END));
        if (i_ret != 0)
            FRLOG_DEBUG_DETAIL("send data failed!\n");
    }
    else
    {
        pthread_rwlock_wrlock(&g_cmd_rwlock);
        g_i_busy = 1;
        pthread_rwlock_unlock(&g_cmd_rwlock);
        /* 根据请求取得结果 */
        i_ret = __do_command(arr_rcv_cmd, i_rcv_len, &p_result, accept_sock);

        pthread_rwlock_wrlock(&g_cmd_rwlock);
        g_i_busy = 0;
        pthread_rwlock_unlock(&g_cmd_rwlock);

        /* 发送结果 */
        if (i_ret == FR_SUCC)
        {
            if (p_result)
            {
                frdbg("frcmd_send_data 1\n");
                i_ret = frcmd_send_data(accept_sock, p_result, strlen(p_result));
            }
            else
            {
                frdbg("frcmd_send_data 2\n");
                i_ret = frcmd_send_data(accept_sock, FRCMD_SERVER_OK, strlen(FRCMD_SERVER_OK));
            }
        }
        else
            i_ret = frcmd_send_data(accept_sock, FRCMD_SERVER_NOT_SUPPORT, strlen(FRCMD_SERVER_NOT_SUPPORT));

        if (i_ret != 0)
            FRLOG_DEBUG_DETAIL("send data failed!\n");

        frcmd_send_data(accept_sock, FRCMD_SERVER_END, strlen(FRCMD_SERVER_END));

        if (p_result)
            frfree(p_result);
    }

    // 结束本次通讯
    close(accept_sock);
    pthread_exit(0);
    return (void*)NULL;
}

/*******************************************************************************
*  FUNC     :  主程序
*  ARGS     :  argc(入力参数个数)
*           :  argv(入力参数)
*  RTN      :  FR_SUCC (success)
*           :  FR_FAIL (failed)
*  NOTE     :
*******************************************************************************/
int frcmd_server_start(int i_port)
{
    int i_ret = 0;
    int listen_sock = 0;
    int accept_sock = 0;
    pthread_t tid;

    /* 检查port值 */
    if (i_port <=0 || i_port > 65535)
    {
        FRLOG_ERROR_DETAIL("Port参数必须是1-65535的整数\n");
        return FR_FAIL;
    }

    i_ret = pthread_rwlock_init(&g_cmd_rwlock, NULL);
    if (i_ret != 0)
    {
        FRLOG_ERROR_DETAIL("pthread_rwlock_init failed\n");
        return FR_FAIL;
    }

    i_ret = __create_listen((unsigned short)i_port, &listen_sock);
    if (i_ret != 0)
    {
        pthread_rwlock_destroy(&g_cmd_rwlock);
        return FR_FAIL;
    }

    {
        fd_set read_flags;
        struct timeval st_wait;

        while (g_i_flag_run)
        {
            /* 接收来自服务器的响应信息，判断是否握手成功 */
            st_wait.tv_sec = 3;
            st_wait.tv_usec = 0;
            FD_ZERO(&read_flags);
            FD_SET(listen_sock, &read_flags);

            if (select(listen_sock + 1, &read_flags, 0, 0, &st_wait) <= 0)
                continue;

            if(FD_ISSET(listen_sock, &read_flags))
            {
                accept_sock = accept(listen_sock, NULL, NULL);
                if(accept_sock < 0)
                {
                    FRLOG_DEBUG_DETAIL("accept失败！\n");
                    continue;
                }

                //创建子线程处理相应
                pthread_create(&tid, NULL, __srv_recv_func, (void *)&accept_sock);
            }
        }
    }

    close(listen_sock);
    pthread_rwlock_destroy(&g_cmd_rwlock);

    return FR_SUCC;
}
